/*
 * @Description:
 * @Version: 2.0
 * @Autor: wiz
 * @Date: 2023-10-17 10:01:05
 * @LastEditors: wiz
 * @LastEditTime: 2024-07-11 18:31:29
 */
import { Tsrv, ifs, ts } from '@/services';
import { N_oMultiForm, N_oSetupPanel } from '@/types';

class T_cmd {
  // 主组件箱
  private compBox: ifs.I_compBox;

  // 主组件ID
  private compID: string;

  // 主组件实例
  private self: N_oMultiForm.oMultiForm;
  // 主组refs

  // 过滤条件
  private filter: any = {};

  // private formsInstances: Map<string, any> = new Map<string, any>();

  // 表格数据（key：表名，value：rows）
  private funRowData = new Map<string, any[]>();

  private originalData = new Map<string, any[]>();

  // 表格变化数据（key：表名，value：rows）
  private funUpdateRecords = new Map<string, any[]>();

  private funInsertRecords = new Map<string, any[]>();

  // private insertRow

  // 多对一
  protected m2oList: N_oMultiForm.I_M2OList[] = [];

  // 字段附加列表
  protected slcList: N_oMultiForm.I_SLCList[] = [];

  private linkParent: any = {
    funName: ``,
    rowID: null,
    mainFunName: null
  };

  // 组件配合 在外部实例化
  private TCoordination: ifs.I_compCoordination;

  private toolbarStatusBak: any = null;

  // 主组件created里初始化
  public init(self: any, compBoxInfo: ifs.I_compBoxInfo) {
    this.self = self;
    this.compBox = compBoxInfo.TcompBox;
    this.compID = compBoxInfo.compID;
  }

  // public regInstance(
  //   compBoxInfo: ifs.I_compBoxInfo,
  //   tableName: string,
  //   key: string
  // ) {
  //   const compID = compBoxInfo.compID;
  //   const compBox = compBoxInfo.TcompBox;
  //   this.formsInstances.set(
  //     key,
  //     compBox.getCompMergeName(compID, `${tableName}_${key}`)
  //   );
  // }

  // public getFormInstance(tableName: string, key: number | string) {
  //   return this.formsInstances.get(`${tableName}_${key}`);
  // }

  public initToolbar(cf: any) {
    if (!Tsrv.utils.noValue(cf.toolbar)) {
      this.self.toolbarList.forEach(el => {
        el.isHide = !cf.toolbar[el.key];
        el.disabled = !cf.toolbar[el.key];
      });
      this.setToolbarStyle('save', 'disabled', true);
    }
  }

  public initFormData(funName: string) {
    this.funRowData.set(funName, []);
    this.originalData.set(funName, Tsrv.utils.clone([]));
  }

  /**
   * @description:设置toolbar按钮的 属性值
   * （1、传参两个值时，第一个值为按钮名-string，第二值为按钮配置-Object、
   *   2、传参三个值时，第一个值为按钮名-string，第二值为按钮属性-string，第三值为指定按钮属性值- boolean/string）
   * @param  btn // 按钮名  string
   * @param  btnKey // 属性名 / 按钮配置 （string / Object）
   * @param  btnValue // 指定属性名的 值  （string | boolean）--可选属性
   * @return void
   * @author: swc
   * @Date: 2023-011-20 20:46:45
   * @LastEditors: swc
   * @LastEditTime: Do not edit
   */
  public setToolbarStyle(
    btn: string,
    // btnKey: string | Object,
    btnKey: any,
    // btnValue?: string | boolean
    btnValue?: any
  ) {
    const button = Tsrv.utils.find(this.self.toolbarList, el => el.key === btn);
    if (
      Object.prototype.toString.call(btnKey) === '[object Object]' &&
      !Tsrv.utils.noValue(btnKey)
    ) {
      Object.keys(btnKey).forEach(key => {
        if (Tsrv.utils.has(button, key)) {
          button[key] = btnKey[key];
        }
      });
    } else if (
      Object.prototype.toString.call(btnKey) === '[object String]' &&
      !Tsrv.utils.noValue(btnValue)
    ) {
      button[btnKey] = btnValue;
    }
  }

  public setFilter(e: any) {
    this.filter = e;
  }

  public loadData() {
    this.originalData.clear();
    this.funUpdateRecords.clear();
    this.funInsertRecords.clear();
    this.self.multiTables.forEach(async el => {
      // 清空数据
      el.formRows = [];
      const [b, res, rows, err] = await this.doLoadData(
        el.funName,
        el.tableName,
        el.dbType
      );
      // this.self.$msg(err ?? res.msg);
      if (b) {
        this.funRowData.set(el.funName, rows);
        this.originalData.set(el.funName, Tsrv.utils.clone(rows));
      } else {
        this.self.$msg(err ?? res.msg);
      }
      // 渲染数据
      this.funRowData.get(el.funName).forEach((row, idx) => {
        el.formRows.push(idx);
      });
    });
    // this.setTableData(substitute);
  }

  public doLoadData(funName: string, tableName: string, dbType: string) {
    const gpd = new ts.T_getPartDataArg();
    gpd.setFilter(this.filter);
    gpd.setFunName(tableName);
    gpd.setTableName(tableName);
    gpd.setDbType(dbType);
    gpd.setLang(this.self.$i18n.locale);
    gpd.setPage(1, 99999);
    gpd.setRule({} as ifs.I_rule);

    return Tsrv.getData(gpd);
  }

  public getFormColumns(funName: string): any[] {
    const t = this.self.multiTables.filter(el => el.funName === funName);
    const formCols = Tsrv.utils.noValue(t) ? [] : t[0].tableColumns;
    //     {
    //       field: 'fbillno',
    //       align: 'left',
    //       folding: false,
    //       params: {
    //         isDefaultFilter: true,
    //         table: 'standard_doc'
    //       },
    //       title: 'fbillno',
    //       itemRender: {
    //         name: 'oInput',
    //         props: {
    //           size: 'small',
    //           disabled: true,
    //           initDisabled: false
    //         },
    //         autoselect: true,
    //         events: null,
    //         attrs: {
    //           actions: {}
    //         }
    //       }
    //     }
    //   ]);
    return formCols;
  }

  // 初始化表格数据
  public setFunForms(funName: string, rowIdx: number, e: any) {
    const cols = this.getFormColumns(funName);
    const ref = this.self.$refs[funName + rowIdx][0];
    const formCol = ref.transformColumns(cols);
    ref.setColumns(formCol);
    const formData = this.funRowData.get(funName)[rowIdx] ?? {};
    ref.setFormData(formData);
    ref.setModify(false);
  }

  /**
   * 设置是否可修改
   */
  public setModify(value: boolean) {
    this.self.multiTables.forEach(el => {
      el.formRows.forEach(ele => {
        this.self.$refs[el.funName + ele][0].setModify(value);
      });
    });
  }

  // 新增
  public async handleInsert(funName: string, formRows: any) {
    this.setModify(true);
    this.self.editStatus = true;
    const formRowsCopy = Tsrv.utils.clone(formRows, true);
    const newIdx = !Tsrv.utils.noValue(formRowsCopy)
      ? formRowsCopy.slice(-1)[0] + 1
      : 0;
    formRows.push(newIdx);
    // ----设置默认值
    this.getComplexFields(funName);
    if (!Tsrv.utils.noValue(this.self.currentMsg)) {
      this.setLinkParent(
        this.self.currentMsg?.option.autoCompleteInfo,
        funName
      );
    }
    this.getDefVal(funName, newIdx).then(insertRowData => {
      this.funRowData.get(funName).push(insertRowData);
      this.setToolbarStyle('save', 'disabled', false);
      this.self.$nextTick(() => {
        this.setFunForms(funName, newIdx, null);
        const newForm = this.self.$refs[funName + newIdx][0];
        this.addFunInsertRecords(funName, newIdx, insertRowData);
        newForm.setModify(true);
      });
    });
  }

  // 向funInsertRecords添加 新增时的默认数据
  private addFunInsertRecords(
    funName: string,
    newIdx: number,
    insertRowData: any
  ) {
    const newForm = this.self.$refs[funName + newIdx][0];
    const changes = [];
    if (!Tsrv.utils.noValue(insertRowData)) {
      Object.keys(insertRowData).forEach(k => {
        if (k !== 'id' && k.indexOf('|') < 0) {
          changes.push({
            field: k,
            value: insertRowData[k]
          });
        }
      });
    }
    if (!this.funInsertRecords.has(funName)) {
      this.funInsertRecords.set(funName, []);
    }
    const insertRecords = this.funInsertRecords.get(funName);
    if (
      Tsrv.utils.noValue(
        Tsrv.utils.find(insertRecords, item => item.id === insertRowData.id)
      )
    ) {
      insertRecords.push({ id: insertRowData.id, changes: [...changes] });
    } else {
      Tsrv.utils.find(
        insertRecords,
        item => item.id === insertRowData.id
      ).changes = [...changes];
    }
  }

  // 获取表的 默认字段
  private getDefVal(funName: string, formID: any) {
    return new Promise((resolve, reject) => {
      const msg = this.self.currentMsg;
      const fields = this.getFields(funName);
      const row: object = {};
      // 获取表格所有的 mto , slc 字段
      const from = msg?.option?.autoCompleteInfo ?? null;
      const m2oList = this.m2oList;
      const linkM2o = {};
      if (!Tsrv.utils.noValue(m2oList) && !Tsrv.utils.noValue(from)) {
        for (const i in m2oList) {
          if (
            m2oList[i].tTable === from.table ||
            m2oList[i].tTable === from.fromTable
          ) {
            linkM2o[m2oList[i].m2oField] = from.data[m2oList[i].tField];
            linkM2o[m2oList[i].field] = from.key;
          }
        }
      }
      fields.forEach(key => {
        if (linkM2o[key] !== undefined) {
          // row[key] = linkM2o[key]; // 设置对应字段
          // row[realField] = linkM2o[realField]; // 设置原字段
          Object.keys(linkM2o).forEach(k => {
            row[k] = linkM2o[k];
          });
        }
        // if (this.slcSetting[key] !== undefined) {
        //   row[key] = this.slcSetting[key]; // 设置对应字段
        // }
        if (key === 'id') {
          row[key] = Tsrv.getSnowIDFmtStr();
        }
        if (!Tsrv.utils.noValue(this.linkParent.defaultVal)) {
          for (const f of this.linkParent.defaultVal) {
            if (f.field === key) {
              row[key] = f.value;
              break;
            }
          }
        }
      });
      // 获取 表格 默认值
      const TdevVal = new ts.T_defVal();
      TdevVal.setLang(this.self.$i18n.locale)
        .setDbType('mysql')
        .setFunName(funName);
      // TdevVal.setMainfunName(this.linkParent.mainFunName).setRowID(
      //   this.linkParent.rowID
      // );
      TdevVal.setMainfunName(null).setRowID(null);
      Tsrv.getDefaultVal(TdevVal)
        .then(fvs => {
          fvs.forEach(fv => {
            if (fields.has(fv.field)) {
              row[fv.field] = fv.value;
            }
          });
          resolve(row);
        })
        .catch(r => {
          throw new Error(r);
        });
    });
  }

  // 获取表格所有字段
  private getFields(funName: string): Set<string> {
    const res: Set<string> = new Set();
    const columns = this.getFormColumns(funName);
    columns.forEach(el => {
      if (el.field) {
        res.add(el.field);
        if (el.field.indexOf('|') > -1) {
          const realField = el.field.split('|')[1];
          res.add(realField);
        }
      }
    });
    if (!res.has('id')) {
      res.add('id');
    }
    return res;
  }

  // 获取表格所有的 mto , slc 字段
  private getComplexFields(funName: string) {
    this.m2oList = [];
    this.slcList = [];
    const columns = this.getFormColumns(funName);
    columns.forEach(e => {
      if (
        e.many2one &&
        e.many2one !== '' &&
        e.many2one.toTable !== '' &&
        e.many2one.toTable !== null
      ) {
        let field = e.field;
        const m2o = Tsrv.utils.getM2OConfig(e.many2one);
        let flag = true;
        for (let i = 0; i < m2o.fields.length; i++) {
          if (m2o.fields[i].isReturn === true) {
            flag = false;
            break;
          }
        }
        if (flag) {
          if (!m2o.toField && !m2o.toTable && !e.field) {
            field = e.field;
          } else {
            field = `m2o|${e.field}|${m2o.toTable}|${m2o.toField}`;
          }
          // 将所有m2o字段添加到
          this.setM2oList({
            field: e.field, // 原始字段
            tTable: m2o.toTable, // 目标表
            tField: m2o.toField, // 目标字段
            m2oField: field // 目标值
          });
        }
      } else if (e.selectionID && e.selectionID !== null) {
        const slcField = `slc|${e.field}|${e.selectionID}`;
        // isSelection = true;
        this.setSlcList({
          field: e.field, // 原始字段
          slcField // 目标值
        });
        // this.validRules[slcField] = this.validRules[e.field];
      } else if (!Tsrv.utils.isEmpty(e.subQuery)) {
        // this.subQueryArr.push(field);
      }
    });
    // return res;
  }

  public setM2oList(...p: N_oMultiForm.I_M2OList[]) {
    this.m2oList.push(...p);
  }

  public setSlcList(...p: N_oMultiForm.I_SLCList[]) {
    this.slcList.push(...p);
  }

  public setLinkParent(v: any, funName: string) {
    this.linkParent = {
      defaultVal: v?.defaultVal ?? [], // 多字段插入默认值
      funName,
      rowID: v.data.id,
      mainFunName: v.table
    };
  }

  // 删除
  public handleDelete(funName: string, rowIdx: number) {
    // const ref = this.self.$refs[funName + rowIdx][0];
    const table = Tsrv.utils.find(
      this.self.multiTables,
      el => el.funName === funName
    );
    const delRowData = Tsrv.utils.clone(
      this.funRowData.get(funName)[rowIdx],
      true
    );
    table.formRows.splice(rowIdx, 1);
    Tsrv.utils.remove(this.funRowData.get(funName), rowIdx);
    // 删除数据 刷新
    this.delCTD(table, `"${delRowData.id}"`).then(e => {
      if (e) {
        this.loadData();
        this.self.editStatus = false;
        this.setToolbarStyle('save', 'disabled', true);
      }
    });
    // this.loadData();
  }

  // 保存
  public handleSave() {
    // 保存前操作
    this.saveCTD().then(e => {
      // 保存成功后
      this.loadData();
      this.self.editStatus = false;
      // 刷新 按钮状态/并设为不可编辑状态
      this.setToolbarStyle('save', 'disabled', true);
      this.setToolbarStyle('edit', {
        title: Tsrv.getI18nByValue('编辑'),
        class: 'wy-bianji1'
      });
    });
  }

  /**
   * 删除操作
   */
  public delCTD(fun: any, id: string) {
    const multiForm = this.self;
    return new Promise((resolve, reject) => {
      const delRec = new ts.T_ctdDelRec();
      delRec.setRule({} as ifs.I_rule);
      if (!Tsrv.utils.noValue(id)) {
        const filter = JSON.parse(`{"id":${id}}`);
        delRec.setFilter(filter);
      } else {
        reject();
      }
      // 删除
      Tsrv.delRows(fun.funName, fun.dbType, {} as ifs.I_rule, delRec).then(
        resp => {
          const [b, res, msg] = resp;
          if (b) {
            msg ? multiForm.$msg(msg) : multiForm.$msg('50002,FE,0,');
            // multiForm.loading = false;
            resolve(true);
          } else {
            // multiForm.loading = false;
            msg ? multiForm.$msg(msg) : multiForm.$msg('-50002,FE,11,');
            reject();
          }
        }
      );
    });
  }

  // 整理 新增/修改的 行数据 (脱离焦点/值改变时触发--把form.getUpdateData()数据带入到funUpdateRecords或者funInsertRecords中)
  public listenDataChange(funName: string, idx: number, e: any) {
    let isNew = true;
    const form = this.self.$refs[funName + idx][0];
    isNew = Tsrv.utils.noValue(
      Tsrv.utils.find(
        this.originalData.get(funName),
        item => item.id === form.localData.id
      )
    );
    const changes = form.getUpdateData();
    if (isNew) {
      if (!this.funInsertRecords.has(funName)) {
        this.funInsertRecords.set(funName, []);
      }
      const insertRecords = this.funInsertRecords.get(funName);
      if (
        Tsrv.utils.noValue(
          Tsrv.utils.find(insertRecords, item => item.id === form.localData.id)
        )
      ) {
        insertRecords.push({ id: form.localData.id, changes: [...changes] });
      } else {
        // Tsrv.utils.find(
        //   insertRecords,
        //   item => item.id === form.localData.id
        // ).changes = [...changes];
        const chas = Tsrv.utils.find(
          insertRecords,
          item => item.id === form.localData.id
        ).changes;
        changes.forEach(item => {
          if (
            Tsrv.utils.findIndexOf(chas, i => i.field === item.field) === -1
          ) {
            chas.push(item);
          } else {
            Tsrv.utils.find(chas, i => i.field === item.field).value =
              item.value;
          }
        });
      }
    } else {
      // this.funUpdateRecords.set(funName, changes);
      if (!Tsrv.utils.noValue(changes)) {
        this.setToolbarStyle('save', 'disabled', false);
        if (!this.funUpdateRecords.has(funName)) {
          this.funUpdateRecords.set(funName, []);
        }
        const updateRecords = this.funUpdateRecords.get(funName);
        if (
          Tsrv.utils.noValue(
            Tsrv.utils.find(
              updateRecords,
              item => item.id === form.localData.id
            )
          )
        ) {
          // if (!Tsrv.utils.noValue(changes))
          updateRecords.push({ id: form.localData.id, changes: [...changes] });
        } else {
          Tsrv.utils.find(
            updateRecords,
            item => item.id === form.localData.id
          ).changes = [...changes];
        }
      }
    }
  }

  private saveCTD() {
    const multiForm = this.self;
    return new Promise((resolve, reject) => {
      const multiTables = Tsrv.utils.clone(this.self.multiTables, true);
      multiTables.forEach((table, index) => {
        const ctd = new ts.T_ctdArg();
        ctd
          .setTableName(table.tableName)
          .setDbType(table.dbType)
          .setRule({} as ifs.I_rule);
        if (!Tsrv.utils.noValue(this.funInsertRecords.get(table.funName))) {
          const insertRecords = this.funInsertRecords.get(table.funName);
          const scope = {};
          // if (this.scope && this.scope?.field) {
          //   scope = { [`${this.scope.field}`]: this.scope.value };
          // }
          const bDatas: ifs.I_baseData[] = [];
          insertRecords.forEach(ele => {
            const bData = new ts.T_baseData();
            bData
              .setDataRule({} as ifs.I_rule)
              .setFileInfo({})
              .setRowData(...(ele.changes as ifs.I_fv[]));
            bDatas.push(bData);
          });
          ctd.setInsRecDataMany(scope, ...bDatas);
        }
        if (!Tsrv.utils.noValue(this.funUpdateRecords.get(table.funName))) {
          const updateRecords = this.funUpdateRecords.get(table.funName);
          let filter: any = {};
          const ctdUpdDatas: ifs.I_ctdUpdData[] = [];
          updateRecords.forEach(item => {
            const ctdUpdData = new ts.T_ctdUpdData();
            ctdUpdData.setDataRule({} as ifs.I_rule).setFileInfo({});
            // const rowData: ifs.I_fv[] = [];
            filter = { id: item.id };
            ctdUpdData.setFilter(filter);
            ctdUpdData.setRowData(...item.changes);
            ctdUpdDatas.push(ctdUpdData);
          });
          ctd.setUpdRecDataMany(...ctdUpdDatas);
        }
        if (
          !Tsrv.utils.noValue(ctd.insertRecords) ||
          !Tsrv.utils.noValue(ctd.updateRecords)
        ) {
          Tsrv.batRows(ctd).then(resp => {
            const [b, res, msg] = resp;
            msg && multiForm.$msg(msg);
            if (b) {
              resolve(true);
            } else {
              reject();
            }
            // multiForm.loading = false;
          });
        }
      });
    });
  }

  // 构建组件协作处理类
  public newTcompCoordination(conf: any) {
    // 组件调度
    this.TCoordination = new ts.T_compCoordination(
      conf.name,
      conf.messageConfig,
      {
        setTempToolbarStatusDisabled: (
          p: N_oSetupPanel.N_comps.T_eventCoordinationToolbar
        ) => {
          this.setTempToolbarStatusDisabled(p);
        },
        setTempToolbarStatusUnDisabled: (
          p: N_oSetupPanel.N_comps.T_eventCoordinationToolbar
        ) => {
          this.setTempToolbarStatusUnDisabled(p);
        },
        cleanSubCompData: (
          p: N_oSetupPanel.N_comps.T_eventCoordinationToolbar
        ) => {
          // 通知组件清空
          this.self.cleanSubCompData(p);
        },
        setMask: (p: boolean) => {
          this.self.isMask = p;
        }
      }
    );
  }

  // 处理组件协调
  public receEventCoordination(
    m: N_oSetupPanel.N_comps.I_eventCoordinationMsg
  ) {
    this.TCoordination.receEventCoordination(m)
      .then(([b, msg]) => {})
      .catch(msg => {
        console.error(msg);
        // this.self.$msg(msg);
      });
  }

  private setTempToolbarStatusDisabled(
    p: N_oSetupPanel.N_comps.T_eventCoordinationToolbar
  ) {
    if (Tsrv.utils.noValue(this.toolbarStatusBak)) {
      this.toolbarStatusBak = Tsrv.utils.clone(this.self.toolbarList, true);
      this.self.toolbarList.forEach(el => {
        el.disabled = true;
      });
    }
  }

  private setTempToolbarStatusUnDisabled(
    p: N_oSetupPanel.N_comps.T_eventCoordinationToolbar
  ) {
    if (!Tsrv.utils.noValue(this.toolbarStatusBak)) {
      this.toolbarStatusBak.forEach(e => {
        this.self.toolbarList.forEach(el => {
          if (e.key === el.key) el.disabled = e.disabled;
        });
      });

      this.toolbarStatusBak = null;
    }
  }

  // 处理组件协调
  public sendEventCoordination(
    type: N_oSetupPanel.N_comps.T_eventCoordinationToolbar
  ) {
    const r = this.TCoordination.sendEventCoordination(type, this.self.$bus)
      .then(([b, msg]) => {})
      .catch(msg => {
        console.error(msg);
        // this.self.$msg(msg);
      });
  }
}
interface I_cmd extends T_cmd {}
export { I_cmd, T_cmd };
